/*
fn drop_slice<T>(slice: &mut [MaybeUninit<T>]) {
    if needs_drop::<T>() {
        for obj in slice.iter_mut() {
            unsafe { obj.assume_init_drop() };
        }
    }
}

pub(crate) fn slice_cast<T>(ptr: NonNull<[u8]>, len: usize) -> NonNull<[T]> {
    let slice = unsafe { from_raw_parts_mut(ptr.cast::<T>().as_ptr(), len) };
    slice.into()
}

pub(crate) fn obj_ctor<F, T>(ptr: NonNull<[u8]>, f: F) -> Result<NonNull<[u8]>, Error>
where
    F: FnOnce(&mut MaybeUninit<T>) -> Result<(), Error>,
{
    let obj = unsafe { ptr.cast::<MaybeUninit<T>>().as_mut() };
    f(obj).map(|_| ptr)
}

pub(crate) fn obj_dtor<T>(ptr: NonNull<[u8]>) {
    if needs_drop::<T>() {
        unsafe {
            let obj = ptr.cast::<T>().as_mut();
            drop_in_place(obj);
        }
    }
}

pub(crate) fn slice_ctor<F, T>(
    ptr: NonNull<[u8]>,
    len: usize,
    mut f: F,
) -> Result<NonNull<[u8]>, Error>
where
    F: FnMut(usize, &mut MaybeUninit<T>) -> Result<(), Error>,
{
    let slice = unsafe { from_raw_parts_mut(ptr.cast::<MaybeUninit<T>>().as_ptr(), len) };
    let mut n: usize = 0;
    for obj in slice.iter_mut() {
        match f(n, obj) {
            Ok(()) => n += 1,
            Err(error) => {
                drop_slice(&mut slice[0..n]);
                return Err(error);
            }
        }
    }
    Ok(ptr)
}

pub(crate) fn slice_dtor<T>(ptr: NonNull<[u8]>, len: usize) {
    if needs_drop::<T>() {
        let slice = unsafe { from_raw_parts_mut(ptr.cast::<MaybeUninit<T>>().as_ptr(), len) };
        drop_slice(slice);
    }
}
*/

pub(crate) fn get_bitfields<const OFF: usize, const BITS: usize>(val: usize) -> usize {
    let mask = ((1_usize << BITS) - 1) << OFF;
    (val & mask) >> OFF
}

pub(crate) fn set_bitfields<const OFF: usize, const BITS: usize>(
    val: usize,
    mut new_val: usize,
) -> usize {
    let mask = (1_usize << BITS) - 1;
    if new_val > mask {
        new_val = mask;
    }
    (val & !(mask << OFF)) | (new_val << OFF)
}

#[cfg(test)]
mod test {
    use super::{get_bitfields, set_bitfields};
    #[test]
    fn test_bitfields() {
        let val = 0xFF_usize;
        let get = get_bitfields::<0, 4>(val);
        assert_eq!(get, 0xF);
        let set = set_bitfields::<0, 4>(val, 0xee);
        assert_eq!(set, 0xFF);
        let get = get_bitfields::<4, 2>(val);
        assert_eq!(get, 3);
        let set = set_bitfields::<4, 2>(val, 2);
        assert_eq!(set, 0xef);
    }
}
